import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteOrder;

public class Client {

	static DatagramSocket dsSocketSend;
	// To define the packet contents according to the protocol
  static class SendPacket{
	  /*to be entered by client 0 -to stop  service
	                            1 -to push string on stack
	                            2 -to pop the stack 
	                            3 -to print the stack*/
	  //String to check command type
	  private String sSendCommand;
	  // string to be pushed on the stack
	  private String sPushString = null;
	  //String to check Endian
	  private int iEndian; 
	  //String to check Data Field
	  private int iCheckData;
	  
	  public void fnSetCommand(String sCommand){
		  this.sSendCommand = sCommand;
	  }
      
	  public String fnCommand(){
		  return sSendCommand;
	  }
	  
	  //Functions to return the data string
	  public void fnSetPushString(String sData){
		  this.sPushString = sData;
	  }
	  
	  public String fnPushString(){
		  return sPushString;
	  }
	  
	  //To return endian info
	  public void fnSetEndian(){
		  ByteOrder bOrder = ByteOrder.nativeOrder();
		  if (bOrder.equals(ByteOrder.BIG_ENDIAN)) 
			  this.iEndian = 1;
		  else 
			  this.iEndian = 0;
	  }
	  
	  public int fnEndian(){
		  return iEndian;
	  }
	  
	  //To return info for commands where packet contains no data
	  public void fnCheckDataField(int iCheckDataField){
		  this.iCheckData = iCheckDataField;
	  }
	  
	  public int fnCheckData(){
		  return iCheckData;
	  }
	  
	  //Function to return the format of the string to be send
	  public String fnFormatPacketString(){
		  return this.fnCommand().concat("^").concat(Integer.toString(this.fnEndian()).concat("&")
		  .concat(Integer.toString(this.fnCheckData())).concat(this.fnPushString()));
	  }
	  
  }
  
  
  
  
		 
  public static void main(String[] args) throws IOException {
			  
			  
			  SendPacket spSendPacket = new SendPacket();
			  String sCommand = null, sPush, sLoop = "y";
			  
			  System.out.println("Enter command:-");
			  System.out.println("Enter '0' to stop client service.");
			  System.out.println("Enter '1' to 'Push' string on stack.");
			  System.out.println("Enter '2' to 'Pop' string from stack.");
			  System.out.println("Enter '3' to 'Print' the stack");
			  
		      //byte[] buffer = sCommand.getBytes();
		   
			  while(true){
				  //read command from command line to send to server
				  BufferedReader brCommand = new BufferedReader(new InputStreamReader(System.in));
				   sCommand = brCommand.readLine();
				  System.out.println("Enter command:-");
				  System.out.println("Enter '0' to stop client service.");
				  System.out.println("Enter '1' to 'Push' string on stack.");
				  System.out.println("Enter '2' to 'Pop' string from stack.");
				  System.out.println("Enter '3' to 'Print' the stack");

				  
				  if(sCommand.trim().equals("1")){
					  
				  System.out.println("Enter String to be send to stack server");
				  sPush = brCommand.readLine();
				  spSendPacket.fnSetPushString(sPush);
                  spSendPacket.fnSetCommand(sCommand);
                  spSendPacket.fnCheckDataField(1);
                  fnPacketSend(spSendPacket);
                   
		             }
			     if(sCommand.trim().equals("2")){
			    	 System.out.println("The popped element from stack server ");
			    	 String sPopped = fnRecievePacket();
			    	 System.out.println(sPopped);
			    	 
			     }
			     if(sCommand.trim().equals("3")){
			    	 System.out.println("All the elements in stack server ");
			    	 String sPopped = fnRecievePacket();
			    	 System.out.println(sPopped);
			    	
			     }
			     if(sCommand.trim().equals("0")){
			     try {
			    	   
			    	    brCommand.close();
			    	    dsSocketSend.close();
			    	    break;
					} catch (IOException eError) {
						System.out.println(eError);
					}
			     }
			     
			  }
			 
		     
		    
		  }

  private static void fnPacketSend(SendPacket spSendPacket) 
  throws IOException{

             int iPort = 5678;
             //Get a datagram socket
           dsSocketSend = new DatagramSocket();
           System.out.println(spSendPacket.fnFormatPacketString());
             //  send the packet    
             InetAddress iaAddress = InetAddress.getByName("127.0.0.1");
           DatagramPacket dpPacket = new DatagramPacket(spSendPacket.fnFormatPacketString().getBytes()
          , spSendPacket.fnFormatPacketString().getBytes().length,iaAddress, iPort); 
          dsSocketSend.send(dpPacket);

}

private static String fnRecievePacket() throws IOException{

        // get response
         DatagramSocket dsSocketRecieve = new DatagramSocket();
                 byte[] bReceivePacket = new byte[1024];

            DatagramPacket dpRecievePacket = new DatagramPacket(bReceivePacket, bReceivePacket.length);

             dsSocketRecieve.receive(dpRecievePacket);

          String sRecieveData =new String( dpRecievePacket.getData());
            return sRecieveData;

}
		  
}